home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / demo / igps_102.zip / TALKSOCK.CPP < prev    next >
C/C++ Source or Header  |  1994-12-01  |  23KB  |  767 lines

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. // Internet Global Phone Project
  3. // talksock.h : Implementation of the CTalkClient, CTalkListenServer, and CTalkServer
  4. //              classes
  5. //
  6. // The CTalk... classes implements protocol specific behaviours on top of the
  7. // CSocketOwner, CSockServer, CSockClient, and CSockListenServer base classes.
  8. // See the main text of article in Dr. Dobb's Journal for a discussion of the
  9. // class hierachy. A discussion of the protocol can also be found in the text.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////////
  12. // Copyright (c) 1993-1994    microWonders Inc.  All rights reserved.
  13. //                                                                         
  14. // AN OPEN INVITION TO BUILD UPON AND CONTRIBUTE TO THE PUBLIC TECHNOLOGY POOL:
  15. // You are encouraged to redistribute, and build upon the technologies presented 
  16. // in this source module and the accompanying article in Dr. Dobb's Journal provided 
  17. // all the conditions listed in the MUSTREAD.TXT file, included with this 
  18. // distribution, are met.
  19. ////////////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h" 
  21. #include "mmsystem.h"
  22. #include "mphone.h"
  23.  
  24. #include "phonedoc.h"  
  25. #include "wsmin.h"
  26. #include "socket.h"  
  27. #include "talksock.h"
  28. #include "phonevw.h"
  29.  
  30.  
  31. #ifdef _DEBUG
  32. #undef THIS_FILE
  33. static char BASED_CODE THIS_FILE[] = __FILE__;
  34. #endif   
  35.  
  36.  
  37.  
  38.  
  39. ////////////////////////////////////////////////////////////////////////////////
  40. // CTalkServer  Class
  41. //
  42. // Philosophy of Implementation:  CONSERVATIVE
  43. //
  44. //    terminate and destroy connection, socket, server, and memory on any error
  45. //
  46. //  -->ensure integrity and security
  47. //
  48. // June 5, 1994     Fix up occasional lockup after send on some WINSOCKs,  the first
  49. //                 Recv on some WINSOCKs gives garbage upon connect.
  50. //
  51. // December 1, 1994        Disabled stringent error checking that caused the
  52. //                        program to abort connection at the slightest excuse
  53. //                        (PA)
  54. //
  55. CTalkServer::CTalkServer()
  56. {
  57.  
  58. }
  59.  
  60. CTalkServer::~CTalkServer()
  61. // Let the Phoneview free memory, since play maynot complete immediately.
  62. // That is, the Server object may be destroyed before audio play completed.   
  63. }  
  64.                                                                            
  65.                                                                            
  66. BOOL CTalkServer::GetBuffer()                                              
  67. {
  68.     // This routine is called by the Listener when dynamically creating
  69.     // a Server object.  The buffer is created to hold the transmitted
  70.     // compressed audio stream.
  71.     //
  72.     m_hspeechBuffer = GlobalAlloc(GHND , (DWORD) COMPRESSED_BUFSIZE);
  73.     if (!m_hspeechBuffer)
  74.     {
  75.       AfxGetMainWnd()->MessageBox("cannot allocate compress buffer!");
  76.       return (FALSE);
  77.     }             
  78.     m_pBuffer = (HPSTR) GlobalLock(m_hspeechBuffer);
  79.     if (!m_pBuffer)
  80.     {
  81.       GlobalUnlock(m_hspeechBuffer);
  82.       GlobalFree(m_hspeechBuffer);
  83.       AfxGetMainWnd()->MessageBox("cannot lock compress buffer!");
  84.       return (FALSE);
  85.     }    
  86.     m_pCurBuf = m_pBuffer;  // set sliding ptr
  87.     return(TRUE);  
  88. }
  89.  
  90.  
  91. void CTalkServer::OnOtherMsgs(int iEvent, int iError)
  92. {     
  93.   // override the 'catch all' virtual function to trap our special
  94.   // WSTALKBEGIN message.  This message is sent as soon as the
  95.   // server thread comes alive.
  96.   //
  97.   // We start the first element of the protocol by sending an
  98.   // ACK.è  if (iEvent == WSTALKBEGIN)
  99.   {
  100.        BOOL bResult;  
  101.        UINT tmpLen;
  102.        
  103.        m_state = S_RESET;
  104.        
  105.        lstrcpy(m_szBuffer, "ACK\r\n");
  106.        TRACE("Server sending first ACK\n");
  107.        tmpLen = lstrlen( m_szBuffer) + 1;         // start with an ACK
  108.        bResult = Send((LPCSTR) m_szBuffer, tmpLen);
  109.        if (bResult != TRUE)
  110.        {
  111.             CallBack(WSCHILDCLOSED, MyLastError());
  112.             CancelIO();
  113.             DestroySocket();
  114.             delete this;
  115.        }
  116.        else
  117.         m_state = S_ACK1;                  
  118.                          
  119.    }
  120. }        
  121.  
  122.  
  123. void CTalkServer::OnReceiveCompleted(int iEvent, int iError)
  124. {     
  125.     // A Winsock receive operation has completed.
  126.     // Handle protocol states requirements here
  127.     //
  128.       if (iError == 0)
  129.       { 
  130.        switch(m_state)
  131.        {
  132.        case S_READSIZE:                          
  133.          // get the audio buffer size to receive
  134.           m_szBuffer[LastRecvLength()] = '\0';
  135.           TRACE("Server got ->%s<-\n", m_szBuffer);            
  136.           m_bufSize  = atol(&m_szBuffer[4]);
  137.           TRACE("Server expect size = ->%lu<-\n", m_bufSize);          
  138.           SendAck();
  139.           break; 
  140.        case S_READTYPE:                         
  141.           // get the audio data type to receive, we only accept 1 type
  142.           m_szBuffer[LastRecvLength()] = '\0';
  143.              m_compressionType = atoi(&m_szBuffer[4]); 
  144.           TRACE("Server got ->%s<-\n", m_szBuffer);             
  145.           SendAck();
  146.           break;
  147.        case S_READDATA:                                              
  148.          // keep reading in small chunks until all audio data are received
  149.           if (DataRead() == DONE)
  150.            {  
  151.             TRACE("Server has completed all data read, sending final ack!\n");           
  152.             SendAck();
  153.            } 
  154.           break;
  155.        }
  156.       }
  157.       else
  158.       {                                        
  159.         TRACE("Disconnect from error code %d\n", iError);      
  160.         CallBack(WSCHILDCLOSED, iError);
  161.         CancelIO();
  162.         DestroySocket();
  163.         delete this;
  164.       }
  165. }
  166.  
  167.  
  168. void CTalkServer::OnSendCompleted(int iEvent, int iError)
  169. {                                                                         
  170.   // Winsock Send operation completed.
  171.   // We handle protocol requirements and transition protocol states
  172.   // here.
  173.      if (iError == 0)
  174.       { 
  175.        BOOL bResult;
  176.        // got an ack sent
  177.        switch (m_state)
  178.        {
  179.         case S_ACK1:
  180.         case S_READTYPE:
  181.         case S_READSIZE:                                    
  182.           // simplified coding: DATACHUNKSIZE is actually too large for
  183.           // S_ACK1 and S_READTYPE states, but it works okay as maximum size
  184.           bResult = Recv((LPSTR) m_szBuffer, DATACHUNKSIZE);
  185.           if (bResult != TRUE)
  186.           {
  187.            CallBack(WSCHILDCLOSED, MyLastError());
  188.            CancelIO();
  189.            DestroySocket();
  190.            delete this;
  191.           }
  192.           else 
  193.            {
  194.              // advance to next state
  195.             m_state = ((m_state == S_ACK1) ? S_READTYPE : 
  196.             ((m_state == S_READTYPE) ? S_READSIZE : S_READDATA));
  197.             
  198.             }
  199.            break;        
  200.          case S_READDATA:
  201.            // final ack, can start processing the data
  202.            // if we want here; we'll just set a flag, and send voice
  203.            // when client disconnects 
  204. TRACE("Server complete sending final ack!\n");           
  205.              m_speechReady = TRUE;
  206.            break;
  207.         } // of switch
  208.            
  209.       } //of iError = 0   
  210.      else
  211.         {
  212.           CallBack(WSCHILDCLOSED, iError);
  213.           CancelIO();
  214.           DestroySocket();
  215.           delete this;
  216.          }
  217. }                
  218.  
  219. UINT CTalkServer::DataRead()
  220. {                
  221.         // got another buffer
  222.                          
  223.        BOOL bResult;
  224.        int RecvSize = LastRecvLength();
  225.                                                  
  226.        ASSERT(RecvSize > 0);                                        
  227.        
  228.         _fmemcpy( m_pCurBuf, m_szBuffer, RecvSize); 
  229.        
  230.         
  231.        m_pCurBuf += RecvSize;     
  232.        
  233.        if (((ULONG)(m_pCurBuf - m_pBuffer)) < m_bufSize)   // need more
  234.        {
  235.          bResult = Recv((LPSTR) m_szBuffer, DATACHUNKSIZE);
  236.          if (bResult != TRUE)
  237.          {
  238.            CallBack(WSCHILDCLOSED, MyLastError());
  239.            CancelIO();
  240.            DestroySocket();
  241.            delete this;
  242.           } 
  243.           
  244.          else 
  245.            return TRUE; 
  246.         }
  247.         else  // don't need any more
  248.         {  
  249.          return (DONE);
  250.         } 
  251.   return TRUE; // never reach here anyway; surpress compiler warning
  252. }
  253.        
  254. void CTalkServer::SendAck()
  255. {
  256.         BOOL bResult;
  257.         UINT tmpLen;
  258.  
  259.       // Routine to send an ACK
  260.       // 
  261.               
  262.         // start with an ACK 
  263.         lstrcpy(m_szBuffer, "ACK\r\n");
  264. TRACE("In Server sending ack = ->%s<-\n", m_szBuffer);
  265.         tmpLen = lstrlen( m_szBuffer) + 1;  // send only enough for compatibility w UNIX   
  266.       bResult = Send((LPCSTR) m_szBuffer, tmpLen);        
  267.        if (bResult != TRUE)
  268.        {
  269.             CallBack(WSCHILDCLOSED, MyLastError());
  270.             CancelIO();
  271.             DestroySocket();
  272.             delete this;
  273.        }
  274.                  
  275.  
  276. }
  277.  
  278. void CTalkServer::OnDisconnected(int iEvent, int iError)
  279. {                                
  280.     if (m_speechReady == TRUE)
  281.     {
  282.      // send voice to output
  283.      // PhoneView will free the buffer after playback
  284.      m_PhoneView->ExpandWaveOut( m_hspeechBuffer, m_pBuffer, m_bufSize);
  285.     
  286.     }
  287.      CallBack(WSCHILDCLOSED, iError);
  288.      Notify(m_socket, WSCHILDCLOSED, iError); 
  289.      CancelIO();
  290.      DestroySocket(); 
  291.      delete this;
  292. }
  293.  
  294. /////////////////////////////////////////////////////////////////////////////
  295. // CTalkServer diagnostics
  296.  
  297. #ifdef _DEBUG
  298. void CTalkServer::AssertValid() const
  299. {
  300.     CSocketOwner::AssertValid();
  301. }
  302.  
  303. void CTalkServer::Dump(CDumpContext& dc) const
  304. {
  305.     CSocketOwner::Dump(dc);
  306. }
  307.  
  308. #endif //_DEBUG
  309.  
  310.  
  311. ////////////////////////////////////////////////////////////////////////
  312. // CTalkClient
  313. //
  314. // Philosophy of Design: CONSERVATIVE
  315. //
  316. // terminate and destroy connection, socket, and client on any error
  317. //                        
  318. // Preferred Philosophy of Design: LIBERAL
  319. //   flow the protocol, let timer detect failure retry and disconnect; this
  320. //   is not implemented here
  321. //
  322. CTalkClient::CTalkClient()
  323. {
  324. }
  325.  
  326. CTalkClient::~CTalkClient()
  327. {
  328. }  
  329.  
  330.  
  331. WSSOCKET CTalkClient::Connect( 
  332.  UINT prot, WSADDRESS iaddress, WSPORTID iPort, UINT uInterval, 
  333.  HWND hCallBack, NOTIFYPROC fNotify, UINT uLimit, HPSTR talkBuffer, ULONG bufLen)
  334. {  
  335.   // make connection and start protocol, UDP is never used currently
  336.   int iProtocol = GetProtocolByName( (prot == TCPSOCK)? "tcp":"udp");
  337.  
  338.   if (iPort == 0)
  339.    iPort=GetServiceByName("intertalk", (prot == TCPSOCK)? "tcp":"udp");
  340.    
  341.   m_socket = CreateSocket(prot, iProtocol,0, sizeof(LPSTR), hCallBack,
  342.  UniversalCSockOwnerNotify);        
  343.  
  344.   if (m_socket != NOTASOCK)
  345.   {                                                      
  346.     // Store a pointer to myself (this object) with the socket
  347.     // associated memory; this allows all socket related messages
  348.     // to find their way back to us. 
  349.     CTalkClient * __far * pto = (CTalkClient * __far *) GetSockMemory();
  350.     *pto = this;
  351.     m_iType = WS_TALKCLIENT;
  352.     // for udp sockets, the address is required
  353. //    if (prot == UDPSOCK) 
  354. //      m_lAddress = GetHostByName(lpName);
  355. //    else
  356. //      m_lAddress = INADDR_NONE;
  357. //    m_uPort = iPort;
  358. //    m_lRecvAddress = INADDR_NONE;
  359. //    m_uSequence = 0;
  360. //    m_bInProgress = FALSE;
  361. //    m_uInterval= (uInterval < MIN_UINTERVAL) ? MIN_UINTERVAL: uInterval;
  362. //    m_uLimit = uLimit;
  363.     m_fNotifyProc = fNotify;
  364.     m_bConnected = (prot == TCPSOCK) ? TRUE: FALSE;
  365.     
  366.     m_talkBuffer = talkBuffer;   
  367.     m_pCurBuf = talkBuffer; 
  368.     
  369.     m_bufLen = bufLen;
  370.  
  371.     if (m_bConnected == TRUE)
  372.     {
  373.       if(ConnectTo(/* MyAddress() */ iaddress, iPort) != TRUE)
  374.       {  
  375.        Notify(m_socket, WSCONNECTED, 998);
  376.        DestroySocket();
  377.        m_socket =  NOTASOCK;    
  378.        }  // of if connect
  379.      }
  380.      else
  381.        Notify(m_socket, WSCONNECTED, 0);
  382.     }  // of if (m_socket != NOTASOCK)
  383.    return (m_socket);
  384. } // of ConnectByName   
  385.       
  386.  
  387.  
  388. void CTalkClient::OnConnected(int iEvent, int iError)
  389.   // Connect completed, we now have a TCP connection.  Start the
  390.   // protocol by waiting for the initial ACK on a Recv.
  391.   
  392.   if (1) //iError == 0)
  393.   { 
  394.       if (CreateTimer(m_uInterval) == TRUE)
  395.       {
  396.       BOOL bResult;
  397.       
  398.       if(m_bConnected == TRUE)
  399.        bResult = Recv((LPSTR) &m_szBuffer, DATACHUNKSIZE);
  400.       
  401.        if (bResult == FALSE)
  402.        { 
  403.          m_state = S_RESET;
  404.          m_bInProgress = FALSE;
  405.         }
  406.        else
  407.         {
  408.           m_state = S_ACK1;
  409.           m_bInProgress = TRUE;
  410.          } 
  411.  
  412.      } // of CreateTimer == TRUE
  413.      else
  414.      {   // unable to create Timer  
  415.        m_bInProgress = FALSE;
  416.        CallBack(WSTALKFAILED, 0);
  417.      } 
  418.  
  419.    } // on iError == 0 
  420.     else
  421.     // not connected         
  422.      { 
  423.       m_bInProgress = FALSE;
  424.       }
  425.  
  426.    CallBack(WSCONNECTED,  iError);       
  427. }  
  428.  
  429.  
  430.  
  431.  
  432. void CTalkClient::OnSendCompleted(int iEvent, int iError)
  433. {           
  434.     // A Winsok Send operation has completed, handle the
  435.     // protocol requirements.  Usually by waiting for an ACK.
  436.     // See Dr. Dobb's Journal text for description of protocol.
  437.     if (iError == 0)
  438.     {
  439.       UINT bStatus;
  440.       switch(m_state)
  441.       {
  442.        case    S_READTYPE:
  443.        case S_READSIZE:                     
  444.            TRACE("In SEND TYPE OR SEND SIZE\n");       
  445.            GetAck();
  446.            break;
  447.        case S_READDATA:              
  448.          TRACE("In SEND DATA PHASE\n");       
  449.          bStatus = SendData();
  450.          if (bStatus == FALSE) // something went wrong
  451.            {  
  452.             TRACE("Something Went wrong in Send Data phase.\n");           
  453.             m_bInProgress = FALSE;
  454.             m_state = S_RESET;
  455.            }
  456.          if (bStatus == DONE)
  457.          {
  458.             TRACE("Send Data Completed! Wait for ACK!\n");            
  459.             GetAck(); // get final ack
  460.           }  
  461.          break;
  462.       }
  463.     }
  464.      else
  465.       {
  466.         m_uErrorCount++;
  467.         m_bInProgress = FALSE;
  468.       }           
  469. }           
  470.  
  471.  
  472. void CTalkClient::OnReceiveCompleted(int iEvent, int iError)
  473. {   
  474.    BOOL bResult;
  475.  
  476.    // A Winsock Recv opertion has completed.  Handle the protocol
  477.    // requirement and mark the state transitions.
  478.    //
  479.    if (1)//(iError == 0)
  480.     { 
  481.      UINT tmpLen;   
  482.      switch(m_state)
  483.      {
  484.     case S_ACK1: // send the type 
  485.         m_szBuffer[LastRecvLength()]='\0';            
  486.         TRACE("Client got %s\n", m_szBuffer);     
  487.            lstrcpy(m_szBuffer, "002 1\r\n");
  488.            tmpLen = lstrlen( m_szBuffer) + 1;  // send only enough for compatibility w UNIX
  489.            bResult = Send((LPCSTR) m_szBuffer, tmpLen);
  490.            if (bResult != TRUE)
  491.            {
  492.             CallBack(WSTALKFAILED, 0);
  493.             m_bInProgress == FALSE;
  494.             m_state = S_RESET;
  495.             OnDisconnected(iEvent, iError);
  496.            }                       
  497.            else
  498.              m_state = S_READTYPE;
  499.          break;
  500.     case S_READTYPE:  // send the size 
  501.         m_szBuffer[LastRecvLength()]='\0';
  502.         TRACE("Client got %s\n", m_szBuffer);     
  503.  
  504.            sprintf( m_szBuffer,"003 %lu\r\n", m_bufLen);   
  505.            TRACE("total COMPRESSED SIZE is: %lu\n", m_bufLen);
  506.            tmpLen = lstrlen(m_szBuffer) + 1; // send just enough
  507.            bResult = Send((LPCSTR) m_szBuffer, tmpLen);
  508.            if (bResult != TRUE)
  509.            {
  510.             CallBack(WSTALKFAILED, 0);
  511.             m_bInProgress == FALSE;
  512.             m_state = S_RESET;     
  513.             OnDisconnected(iEvent, iError);
  514.            }                       
  515.            else
  516.              m_state = S_READSIZE;
  517.            break;
  518.     case S_READSIZE:  // send the data  
  519.     m_szBuffer[LastRecvLength()]='\0';
  520.     TRACE("Client got %s\n", m_szBuffer);     
  521.  
  522.          // in case there's less data to sent than 1 block
  523.          m_lastSentSize = (m_bufLen > (ULONG) DATACHUNKSIZE) ? DATACHUNKSIZE : (UINT) m_bufLen;    
  524.     TRACE("Sending %d bytes...\n", m_lastSentSize);      
  525.          if (m_bConnected == TRUE)
  526.            bResult = Send((LPCSTR) m_pCurBuf, m_lastSentSize);
  527.          else
  528.            bResult = SendTo((LPCSTR) m_pCurBuf, m_lastSentSize, m_lAddress, m_uPort);
  529.            
  530.         if (bResult == FALSE)
  531.          { 
  532.            CallBack(WSTALKFAILED, 0);
  533.            m_bInProgress = FALSE;
  534.            m_uErrorCount++;  
  535.            OnDisconnected(iEvent, iError);
  536.          }
  537.          else 
  538.            {
  539.            m_bInProgress = TRUE;
  540.            m_state = S_READDATA;     
  541.  
  542.            }
  543.          break;
  544.     case S_READDATA: // done, got final ack, wrap up
  545.         TRACE("it is FINAL, got last ack, We're wrapping up.\n");       
  546.           OnDisconnected(iEvent, iError);
  547.           break;
  548.     } // of case
  549.       
  550.     } // of iError==0
  551.     else
  552.     {      
  553.       CallBack(WSTALKFAILED, 0);
  554.       m_uErrorCount++;
  555.       m_bInProgress = FALSE;
  556.       OnDisconnected(iEvent, iError);
  557.     }    
  558. }           
  559.  
  560. UINT CTalkClient::SendData()
  561. {
  562.    // break up the large block of data into multiple small sends
  563.    // to fit through the max buffer size allowed by Winsock
  564.  
  565.       m_pCurBuf += m_lastSentSize;  // mark another chunk sent
  566.       if (m_pCurBuf  <  (m_talkBuffer  + m_bufLen)) // NOT everything sent
  567.       {
  568.          BOOL bResult;
  569.          m_uAttempts++;                                   
  570.          UINT tmpval = (UINT)((m_talkBuffer + m_bufLen) - m_pCurBuf);
  571.          // potentially send last remaining block
  572.          m_lastSentSize = (tmpval > DATACHUNKSIZE) ? DATACHUNKSIZE : tmpval;    
  573.        TRACE("ACTUALLY Sending %d values\n", m_lastSentSize);           
  574.          if (m_bConnected == TRUE)
  575.           bResult = Send((LPCSTR) m_pCurBuf, m_lastSentSize);
  576.  
  577.  
  578.          if (bResult == FALSE)
  579.          {
  580.            m_bInProgress = FALSE;
  581.            m_uErrorCount++;                      
  582.            return FALSE;
  583.          }
  584.          else
  585.           { 
  586.             m_bInProgress = TRUE;
  587.             return TRUE;
  588.           } 
  589.      } // not everything send
  590.      else
  591.        return (DONE);
  592.                 
  593. }      
  594.  
  595. void CTalkClient::GetAck()
  596. {
  597.   BOOL bResult;
  598.       m_lRecvAddress = INADDR_NONE;
  599.           
  600.       if(m_bConnected == TRUE)
  601.          bResult = Recv((LPSTR) &m_szBuffer, DATACHUNKSIZE);
  602.       else
  603.         bResult = RecvFrom((LPSTR) &m_szBuffer, WSTALKBUFFERSIZE, 
  604.         (LPWSADDRESS) &m_lRecvAddress, (LPWSPORTID) &m_uRecvPort);
  605.       
  606.        if (bResult == FALSE)
  607.        { 
  608.     TRACE("Inside Get Ack, something went wrong!\n");       
  609.          m_state = S_RESET;
  610.          m_bInProgress = FALSE;
  611.         }
  612.        else
  613.         {
  614.           m_bInProgress = TRUE;
  615.         } 
  616.    
  617.   
  618.  
  619. void CTalkClient::OnTimerExpired(int iEvent, int iError)
  620. {
  621.   // Timer is not used currently.  Definitely can be used to
  622.   // make the protocol more robust by re-trying and/or 
  623.   // aborting after time-out, etc.
  624.   
  625.   if (KillTimer() == TRUE)
  626.    {  // timed out
  627.    }
  628.    CallBack(WSTALKBACK, 0);
  629. }
  630.    
  631.  
  632. void CTalkClient::OnDisconnected(int iEvent, int iError)
  633. {
  634.    KillTimer();
  635.    m_bInProgress = FALSE;
  636.   TRACE("Inside OnDisconnected!\n");
  637.    CancelIO();
  638.    CallBack(WSDISCONNECTED, iError);  
  639.    DestroySocket();  // kill it off
  640. }   
  641.  
  642. BOOL CTalkClient::End()
  643. {
  644.  BOOL bResult;
  645.  if (m_iType == WS_TALKCLIENT)
  646.    bResult = DestroySocket();
  647.  else
  648.    bResult = FALSE;
  649.  return bResult;
  650. }
  651.  
  652. /////////////////////////////////////////////////////////////////////////////
  653. // CSocketClient diagnostics
  654.  
  655. #ifdef _DEBUG
  656. void CTalkClient::AssertValid() const
  657. {
  658.     CSocketOwner::AssertValid();
  659. }
  660.  
  661. void CTalkClient::Dump(CDumpContext& dc) const
  662. {
  663.     CSocketOwner::Dump(dc);
  664. }
  665.  
  666. #endif //_DEBUG
  667.  
  668. ////////////////////////////////////////////////////////////////////////
  669. // CTalkListenServer
  670. //
  671. // Listen at the well-known port.  Upon foregin connection, dynamically
  672. // create a Server object, allocate memory, and start the server thread's
  673. // protocol handler.
  674. //
  675. CTalkListenServer::CTalkListenServer()
  676. {
  677.     // TODO: add member initialization code here
  678. }
  679.  
  680. CTalkListenServer::~CTalkListenServer()
  681. {
  682. }  
  683.  
  684.  
  685. WSSOCKET CTalkListenServer::StartListener(LPCSTR lpName, 
  686.  WSPORTID Port, LPWSADDRESS ConnAddr, HWND hCallBack, NOTIFYPROC fCallBack,  CPhoneView * phView)
  687. {
  688.   m_PhoneView = phView;                                                   
  689.                                                      
  690.   return (CSockListenServer::StartListener(lpName, Port, ConnAddr, hCallBack, fCallBack));
  691. }
  692.  
  693. void CTalkListenServer::OnOtherMsgs(int iEvent, int iError)  
  694. {                   
  695.  // override the virtual 'catch-all' and intercepts the Accept() message
  696.  // to spin-off our Protocol specific Server process
  697.  //
  698.    if (iEvent == WSACCEPTCOMPLETE && (WSSOCKET)iError != NOTASOCK)
  699.    {
  700.      WSSOCKET iNewSocket = AttachSocket((HSOCK)iError, (int) sizeof(LPSTR),
  701.       MyCallBack(),
  702.      (NOTIFYPROC) UniversalCSockOwnerNotify);    
  703.  
  704.       
  705.       if (iNewSocket != NOTASOCK)  // attach sucessful
  706.       {                                                      
  707.       CTalkServer * nuServer = new(CTalkServer);   
  708.       if (nuServer != NULL)
  709.       {   
  710.        nuServer->SetSafeSocket(iNewSocket);
  711.        nuServer->m_PhoneView = m_PhoneView;
  712.  
  713.        if (nuServer->GetBuffer() == TRUE)  // try to allocate full speech Buffer 1st
  714.         { 
  715.          CTalkServer * __far * optr = (CTalkServer * __far *) nuServer->GetSockMemory();
  716.          if (optr != NULL)    
  717.          {                           
  718.           *optr = nuServer;
  719.           nuServer->m_fNotifyProc = m_fNotifyProc;
  720.           nuServer->m_iType = WSTALKCHILD;             
  721.           
  722.           nuServer->Notify(iNewSocket, WSTALKBEGIN, 0); 
  723.           CallBack( WSTALKNEWCHILD, (int) iNewSocket);       
  724.           }
  725.          else       
  726.           {
  727.           Notify(m_socket, WSTALKLISFAILED, IGP_NOMEM);
  728.           nuServer->DestroySocket(); 
  729.           delete nuServer;
  730.           } 
  731.         } // GetBuffer()
  732.        else
  733.           {  
  734.           Notify(m_socket, WSTALKLISFAILED, IGP_NOMEM);
  735.           nuServer->DestroySocket();
  736.           delete nuServer;
  737.           }
  738.       } // of nuServer != NULL        
  739.       else                                
  740.         {
  741.         Notify(m_socket, WSTALKLISFAILED, IGP_NOMEM);
  742.         WSDestroySocket(iNewSocket);    
  743.         }
  744.       }  // iNewSocket
  745.      }  // of iEvent   
  746. }
  747.  
  748. /////////////////////////////////////////////////////////////////////////////
  749. // CTalkListenServer diagnostics
  750.  
  751. #ifdef _DEBUG
  752. void CTalkListenServer::AssertValid() const
  753. {
  754.     CSocketOwner::AssertValid();
  755. }
  756.  
  757. void CTalkListenServer::Dump(CDumpContext& dc) const
  758. {
  759.     CSocketOwner::Dump(dc);
  760. }
  761.  
  762. #endif //_DEBUG
  763.  
  764.